package com.tanhua.mongo.api;

/**
 * @Author: cl
 * @Date: 2022/5/3 - 05 - 03
 * @Description:
 */

import cn.hutool.core.collection.CollUtil;
import com.tanhua.dubbo.api.RecommendUserApi;
import com.tanhua.model.dto.RecommendUserDto;
import com.tanhua.model.mongo.RecommendUser;
import com.tanhua.model.mongo.UserLike;
import com.tanhua.model.vo.PageResult;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.util.List;

/**
 * 匹配缘分值服务
 */
@DubboService
public class RecommendUserApiImpl implements RecommendUserApi {

    //mongo数据库操作模板对象
    @Autowired
    private MongoTemplate mongoTemplate;


    /**
     * 查询今日佳人
     *
     * @param toUserId
     * @return
     */
    @Override
    public RecommendUser queryWithMaxScore(Long toUserId) {
        //1、根据用户id查询最高缘分值的用户id(先排序，再获取第一个)

        //构建Criteria设置条件
        Criteria criteria = Criteria.where("toUserId").is(toUserId);

        //构建Query对象
        Query query = new Query(criteria).with(Sort.by(Sort.Order.desc("score"))).limit(1);

        //查询
        RecommendUser recommendUser = mongoTemplate.findOne(query, RecommendUser.class);

        return recommendUser;
    }

    /**
     * 分页查询缘分匹配列表
     *
     * @param page
     * @param pagesize
     * @param toUserId
     * @return
     */
    @Override
    public PageResult queryRecommendUserList(Integer page, Integer pagesize, Long toUserId) {
        //构建Criteria设置条件
        Criteria criteria = Criteria.where("toUserId").is(toUserId);
        //构建Query对象
        Query query = new Query(criteria);
        //查询总记录数(在分页设置之前查询)
        long count = mongoTemplate.count(query, RecommendUser.class);
        //设置分页
        query.limit(pagesize).skip((page - 1) * pagesize).with(Sort.by(Sort.Order.desc("score")));

        //查询数据
        List<RecommendUser> recommendUsers = mongoTemplate.find(query, RecommendUser.class);
        //封装数据
        PageResult pageResult = new PageResult(page, pagesize, count, recommendUsers);
        return pageResult;
    }

    /**
     * 通过用户id和推荐用户id查询推荐值
     *
     * @param userId
     * @param toUserId
     * @return
     */
    @Override
    public RecommendUser findByUserIdAndToUserId(Long userId, Long toUserId) {
        //1、创建条件
        Query query = Query.query(Criteria.where("userId").is(userId).and("toUserId").is(toUserId));
        //2、查询数据库
        RecommendUser one = mongoTemplate.findOne(query, RecommendUser.class);
        //3、判断是否有推荐值
        if (one == null) {
            //3.1没有给创建个
            one = new RecommendUser();
            one.setUserId(userId);
            one.setToUserId(toUserId);
            one.setScore(100d);
        }
        //3.2有直接返回
        return one;
    }

    /**
     * 获取用户推荐(排除喜欢和不喜欢的并限制数量)
     *
     * @param userId
     * @param i
     * @return
     */
    @Override
    public List<RecommendUser> queryCardsList(Long userId, int i) {
        //1、查询用户喜欢和不喜欢的id
        List<UserLike> likes = mongoTemplate.find(Query.query(Criteria.where("userId").is(userId)), UserLike.class);
        List<Long> likeUserId = CollUtil.getFieldValues(likes, "likeUserId", Long.class);
        //2、构造条件查询(排除已经喜欢或者不喜欢的)
        Criteria criteria = Criteria.where("toUserId").is(userId).and("userId").nin(likeUserId);
        //3、使用统计函数，随机推荐的用户
        TypedAggregation<RecommendUser> t = TypedAggregation.newAggregation(
                RecommendUser.class,
                TypedAggregation.match(criteria),//指定得条件
                Aggregation.sample(i)//指定多少条
        );
        //4、根据统计函数查询数据库
        AggregationResults<RecommendUser> aggregate = mongoTemplate.aggregate(t, RecommendUser.class);
        return aggregate.getMappedResults();
    }
}
